package com.sikaryofficial.system.api.config;

import cn.hutool.core.io.IoUtil;
import feign.FeignException;
import feign.Response;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.lang.reflect.Type;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.Map;

@Slf4j
public class HiSMKDigResponseDecoder implements Decoder {

    private static final String RESPONSE_HEADER_ENCRYPTED = "X-Encrypted";
    private static final String RESPONSE_HEADER_ALGORITHM = "Algorithm";

    private final Decoder delegate;
    private final Map<String, DecryptComponent> decryptComponents;

    public HiSMKDigResponseDecoder(Decoder delegate, Map<String, DecryptComponent> decryptComponents) {
        this.delegate = delegate;
        this.decryptComponents = decryptComponents;
    }
    @Override
    public Object decode(Response response, Type type) throws IOException, DecodeException, FeignException {
        if (!isEncrypted(response)) {
            log.debug("Response is not encrypted");
            return delegate.decode(response, type);
        }
        String algorithm = algorithm(response);
        log.debug("Decrypting response with algorithm: {}", algorithm);
        Response.Body body = response.body();
        String read = IoUtil.read(body.asReader(StandardCharsets.UTF_8));
        String decrypt = decrypt(read, algorithm);

        Response decryptedResponse = response.toBuilder()
                .body(decrypt.getBytes(StandardCharsets.UTF_8))
                .build();

        return delegate.decode(decryptedResponse, type);
    }

    private String decrypt(String data, String algorithm) {
        DecryptComponent decryptComponent = decryptComponents.get(algorithm);
        if (decryptComponent == null) {
            return data;
        }
        return decryptComponent.decrypt(data);
    }

    /**
     * 是否加密
     * @param response
     * @return
     */
    private boolean isEncrypted(Response response) {
        Map<String, Collection<String>> headers = response.headers();
        Collection<String> strings = headers.get(RESPONSE_HEADER_ENCRYPTED);
        return strings != null && strings.contains("true");
    }

    /**
     * 获取加密算法
     * @param response
     * @return
     */
    private String algorithm(Response response) {
        Map<String, Collection<String>> headers = response.headers();
        Collection<String> strings = headers.get(RESPONSE_HEADER_ALGORITHM);
        if (strings == null || strings.isEmpty()) {
            return null;
        }
        return strings.iterator().next();
    }
}
